<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>

<body>
    <script>
        //【笔记】reduce()也是数组Array.prototype几个重要方法

        //就是你拿着钱包，一个个数过去看里面有多少钱，每检查一个，就和前面综合加起来，结束时候就知道总共多少钱了。//兼容：ie678不支持


        //reduce是JavaScript 1.8中才引入的，中文意思为“减少”、“约简”。不过，从功能来看，
        // 我个人是无法与“减少”这种含义联系起来的，反而更接近于“迭代”、“递归(recursion)”，
        //擦，因为单词这么接近，不会是ECMA-262 5th制定者笔误写错了吧~~


        //语法：array.reduce(callback[, initialValue])
        //callback函数接受4个参数：之前值、当前值、索引值以及数组本身。
        // initialValue参数可选，表示初始值。若指定，则当作最初使用的previous值；
        //initialValue这个参数和第一个参数是一个位置，写了就是previous，没写就是默认第一个是
        // 如果缺省，则使用数组的第一个元素作为previous初始值，同时current往后排一位，
        // 相比有initialValue值少一次迭代。


        //【##】当我们需要操作数组每个元素，最后仅有一个返回值，适合reduce方法
        //(1-1)此处演示没有使用initalValue初始值。【下面应用，求数组所有项的加和】
        const numbers = [5, 10, 15];
        const total = numbers.reduce((accumulator, currentValue) => accumulator + currentValue);
        //【警示：将上面的es6语法转换为es2015语法】
        var sum = [1, 2, 3, 4].reduce(function(previous, current, index, array) {
            return previous + current;
        });
        console.log(sum); // 10




        //（1-2）有了reduce，我们可以轻松实现二维数组的扁平化：
        var matrix = [
            [1, 2],
            [3, 4],
            [5, 6]
        ];
        //（2-1） 二维数组扁平化
        var flatten = matrix.reduce(function(previous, current) {
            return previous.concat(current);
        });
        console.log(flatten); // [1, 2, 3, 4, 5, 6]



        //解释（1-1）：
        //    // 初始设置
        //    previous = initialValue = 1, current = 2
        //    // 第一次迭代
        //    previous = (1 + 2) =  3, current = 3
        //    // 第二次迭代
        //    previous = (3 + 3) =  6, current = 4
        //    // 第三次迭代
        //    previous = (6 + 4) =  10, current = undefined (退出)
        //（3-1）计算数组中每个元素出现的次数
        var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
        var countedNames = names.reduce(function(allNames, name) {
            if (name in allNames) {
                allNames[name]++;
            } else {
                allNames[name] = 1;
            }
            return allNames;
        }, {});
        console.log(countedNames); // { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
        //（4-1）使用扩展运算符和initialValue绑定包含在对象数组中的数组
        // friends - an array of objects
        // where object field "books" - list of favorite books
        var friends = [{
            name: 'Anna',
            books: ['Bible', 'Harry Potter'],
            age: 21
        }, {
            name: 'Bob',
            books: ['War and peace', 'Romeo and Juliet'],
            age: 26
        }, {
            name: 'Alice',
            books: ['The Lord of the Rings', 'The Shining'],
            age: 18
        }];

        // allbooks - list which will contain all friends' books +
        // additional list contained in initialValue
        var allbooks = friends.reduce(function(prev, curr) {
            return [...prev, ...curr.books];
        }, ['Alphabet']);
        console.log(allbooks); //
        // allbooks = [
        //   'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
        //   'Romeo and Juliet', 'The Lord of the Rings',
        //   'The Shining'
        // ]
        //（5-1）数组去重
        let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
        let result = arr.sort().reduce((init, current) => {
            if (init.length === 0 || init[init.length - 1] !== current) {
                init.push(current);
            }
            return init;
        }, []);
        console.log(result); //[1,2,3,4,5]
    </script>
</body>

</html>